package com.tanzc.mp3player.utils;

import sun.jvmstat.monitor.*;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: tanzc
 * @date: 9:40 2021/5/8
 **/
public class ProcessUtil {
    /**
     * <p> Description: cmd: tasklist | findstr 'findstr'</p>
     *
     * @param findstr 对tasklist的结果筛选
     * @return java.util.List<java.util.List < java.lang.String>>
     **/
    public List<List<String>> getSystemProcesses(String findstr) throws IOException {
        List<List<String>> taskList = getSystemProcesses();
        taskList = taskList.stream().filter(task -> {
            for (String prop : task) {
                if (prop.contains(findstr)) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return taskList;
    }

    /**
     * <p> Description: cmd: tasklist</p>
     *
     * @return java.util.List<java.util.List < java.lang.String>>
     **/
    public List<List<String>> getSystemProcesses() throws IOException {
        ProcessBuilder pb = new ProcessBuilder("tasklist");
        Process p = pb.start();
        BufferedReader out = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getInputStream()), Charset.forName("GB2312")));
        BufferedReader err = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getErrorStream()), Charset.forName("GB2312")));
        System.out.println("Window 系统进程列表");
        String ostr;

        List<String> task = new ArrayList<>();
        List<List<String>> taskList = new ArrayList<>();
        String pidSession = null;

        // 遍历 tasklist 命令返回的进程列表
        while ((ostr = out.readLine()) != null) {
            System.out.println(ostr);
            // 前三行不放进List
            if (!ostr.isEmpty() && !ostr.contains("PID") && !ostr.contains("==")) {
                // 去除多余的空字符
                task = new ArrayList<>(Arrays.asList(ostr.split("\\s{2,}")));
                // pid 和 session列只隔了一个空格，需要再次分割添加，并删掉该项
                pidSession = task.get(1);
                task.addAll(1, new ArrayList<>(Arrays.asList(pidSession.split(" "))));
                task.remove(pidSession);
                taskList.add(task);
            }
        }
        String estr = err.readLine();
        if (estr != null) {
            System.out.println("\nError Info");
            System.out.println(estr);
        }
        return taskList;
    }

    /**
     * <p> Description: 根据processId杀死进程</p>
     * @param processId processId
     **/
    public void killProcess(Integer processId) throws IOException {
        // 这里要注意ProcessBuilder支持多command命令，还支持传入list。另外它不支持命令中有空格，所有多参数就分开写，不然报错
        ProcessBuilder pd = new ProcessBuilder("taskkill", "/pid", processId.toString(), "/f");
        Process p = pd.start();

        BufferedReader out = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getInputStream()), Charset.forName("GB2312")));
        BufferedReader err = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getErrorStream()), Charset.forName("GB2312")));
        String ostr;

        while ((ostr = out.readLine()) != null) {
            System.out.println(ostr);
        }
        String estr = err.readLine();
        if (estr != null) {
            System.out.println("\nError Info");
            System.out.println(estr);
        }
    }

    /**
     * <p> Description: 根据提供的参数创建进程</p>
     * @param command command
     **/
    public void startWithProcessBuilder(String... command) throws IOException {
        ProcessBuilder pd = new ProcessBuilder(command);
        Process p = pd.start();

        BufferedReader out = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getInputStream()), Charset.forName("GB2312")));
        BufferedReader err = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getErrorStream()), Charset.forName("GB2312")));
        String ostr;

        while ((ostr = out.readLine()) != null) {
            System.out.println(ostr);
        }
        String estr = err.readLine();
        if (estr != null) {
            System.out.println("\nError Info");
            System.out.println(estr);
        }
    }

    public void startWithRuntimeExec(String arg) throws IOException {
        Process p = Runtime.getRuntime().exec("cmd /c " + arg);
    }

    /**
     * <p> Description: 获取所有正在运行的java虚拟机</p>
     *
     * @return java.util.Map<java.lang.Object, java.lang.String>
     **/
    public Map<Object, String> getAllRuningJava() throws URISyntaxException, MonitorException {
        MonitoredHost local = MonitoredHost.getMonitoredHost("localhost");

        Set<?> vmList = new HashSet<>(local.activeVms());

        Map<Object, String> processClass = new HashMap<>();

        for (Object process : vmList) {
            // 这里process其实就是pid
            MonitoredVm vm = local.getMonitoredVm(new VmIdentifier("//" + process));
            // 获取类名
            String processname = MonitoredVmUtil.mainClass(vm, true);
            processClass.put(process, processname);
//            System.out.println(process + " -----> " + processname);
        }
        return processClass;
    }
}
